package commands

import (
	"context"
	"fmt"
	"os"
	"strings"

	cli "github.com/urfave/cli/v3"

	"github.com/containerd/containerd"
	"github.com/containerd/containerd/namespaces"
	"github.com/dustin/go-humanize"
)

type printCfg struct {
	discription string
	fmt         string
	show        bool
}

// 设置打印的格式表
var containerListPrint = []printCfg{
	{"CONTAINER ID", "%-20s", true},
	{"IMAGE", "%-40s", true},
	{"STATUS", "%-15s", true},
	{"CREATED", "%-20s", true},
}

var listCommand = &cli.Command{
	Name:      "list",
	Aliases:   []string{"ls"},
	Usage:     "List containers",
	UsageText: "ruc List [options]",

	Flags: []cli.Flag{
		&cli.BoolFlag{
			Name:    "quiet",
			Aliases: []string{"q"},
			Usage:   "Only display container IDs",
		},
	},

	Action: list,

	ErrWriter:       os.Stderr,
	CommandNotFound: commandNotFoundHandler,
	ExitErrHandler:  exitErrHandler,
}

func list(ctx context.Context, cmd *cli.Command) error {
	client, err := containerd.New(
		containerdAddress,
		containerd.WithDefaultNamespace(namespaces.Default),
	)
	if err != nil {
		return err
	}
	defer client.Close()

	containers, _ := client.Containers(ctx)
	if cmd.Bool("quiet") {
		for _, container := range containers {
			fmt.Println(container.ID())
		}
		return nil
	}

	for _, header := range containerListPrint {
		if header.show {
			fmt.Printf(header.fmt, header.discription)
		}
	}
	fmt.Println()

	for _, container := range containers {
		info, err := container.Info(ctx)
		if err != nil {
			fmt.Fprintf(cmd.ErrWriter, "%q: %s\n", cmd.FullName(), err)
			continue
		}

		var s string
		task, err := container.Task(ctx, nil)
		if err != nil {
			s = ""
		} else {
			status, err := task.Status(ctx)
			if err != nil {
				fmt.Fprintf(cmd.ErrWriter, "%q: %s\n", cmd.FullName(), err)
				continue
			}
			s = string(status.Status)
		}

		// 优雅打印
		item := []interface{}{
			info.ID,                       // CONTAINER ID
			info.Image,                    // IMAGE
			strings.ToUpper(s),            // STATUS
			humanize.Time(info.CreatedAt), // CREATED
		}
		for i := range item {
			if containerListPrint[i].show {
				fmt.Printf(containerListPrint[i].fmt, item[i])
			}
		}
		fmt.Println()
	}

	return nil
}
